package com.rowline.admin.module.study.collections;

import java.util.ArrayList;
import java.util.List;

/**
 * ClassName:ArrayListRemoveTest
 * Created by 245167
 * on 2017/11/17  17:06
 * description:
 */
public class ArrayListRemoveTest {

    public static void main(String[] args) {
        List<String> strList = new ArrayList<String>();

        strList.add("aa");
        strList.add("bb");
        strList.add("ab");
        strList.add("ac");
        strList.add("bb");
        strList.add("aaa");
        strList.add("bb");
        strList.add("bb");
        strList.add("bb");

        System.out.println("原list ==> " + strList.toString());

        /**
         * 方式一：for循环遍历list
         * 这种方式的问题在于，删除某个元素后，list的大小发生了变化，
         * 而你的索引也在变化，所以会导致你在遍历的时候漏掉某些元素。
         * 比如当你删除第1个元素后，继续根据索引访问第2个元素时，
         * 因为删除的关系后面的元素都往前移动了一位，所以实际访问的是第3个元素。
         * 因此，这种方式可以用在删除特定的一个元素时使用，但不适合循环删除多个元素时使用。
         */
//        String target = null;
//        for(int i = 0; i < strList.size(); i++){
//            System.out.println("i = " + i);
//            if("bb".equals(target)){
//                // strList.remove(target)
//                System.out.println("strList.size() = " + strList.size());
//                strList.remove(i);
//            }
//        }
//        System.out.println("for n=i ==> " + strList.toString());

//        针对这种情况可以倒序删除的方式来避免。
//        解决办法如下：
//
//        public static void remove(ArrayList<String> list){
//            for(int i=list.size()-1;i>=0;i--){
//                String s=list.get(i);
//                if(s.equals("bb")){
//                    list.remove(s);
//                }
//            }
//        }
//        因为数组倒序遍历时即使发生元素删除也不影响后序元素遍历。

        /**
         * 方式二：for增强
         * 这种方式的问题在于，删除元素后继续循环会报错误信息ConcurrentModificationException，
         * 因为元素在使用的时候发生了并发的修改，导致异常抛出。
         * 但是删除完毕马上使用break跳出，则不会触发报错。
         */
        // [aa, bb, ab, ac, bb, aaa, bb, bb, bb]
        for(String s:strList){
            if("bb".equals(s)){
                strList.remove(s);
            }
        }
        System.out.println("增强for循环 ==> " + strList.toString());
//        ArrayList集合中remove方法底层的源码中有一个fastRemove(index)方法，
//        然后会有一个modCount++的操作，然后在ArratList内部的迭代器中有一个checkForComodification操作，
//        也就是检查modCount是否改变，如果改变了，就抛出并发修改错误。


        /**
         * 方式三：Iterator遍历
         * 这种方式可以正常的循环及删除。
         * 但要注意的是，使用iterator的remove方法，
         * 如果用list的remove方法同样会报上面提到的ConcurrentModificationException错误。
         */
//        Iterator<String> iterator = strList.iterator();
//        while(iterator.hasNext()){
//            String x = iterator.next();
//            if(("bb").equals(x)){
//                iterator.remove();
//            }
//        }
//        System.out.println("iterator遍历 ==> " + strList);

        /**
         * 总结：
         　　（1）循环删除list中特定一个元素的，可以使用三种方式中的任意一种，但在使用中要注意上面分析的各个问题。
         　　（2）循环删除list中多个元素的，应该使用迭代器iterator方式。
         */



    }


}
